homework 10, version 0
Submission by: Jazzy Doe (jazz@mit.edu)
Homework 10: Climate modeling II
18.S191
, fall 2020
"Jazzy Doe"
"jazz"
Let's create a package environment:
Activating new project at `/tmp/jl_VhqMdx` Updating registry at `~/.julia/registries/General.toml` Resolving package versions... Updating `/tmp/jl_VhqMdx/Project.toml` [6e4b80f9] + BenchmarkTools v1.6.0 [5789e2e9] + FileIO v1.17.0 [82e4d734] + ImageIO v0.6.9 [6218d12a] + ImageMagick v1.4.2 [916415d5] + Images v0.26.2 [6fe1bfb0] + OffsetArrays v1.17.0 [5432bcbf] + PaddedViews v0.5.12 [91a5bcdd] + Plots v1.40.14 [7f904dfe] + PlutoUI v0.7.64 [ac1d9e8a] + ThreadsX v0.1.12 Updating `/tmp/jl_VhqMdx/Manifest.toml` [621f4979] + AbstractFFTs v1.5.0 [6e696c72] + AbstractPlutoDingetjes v1.3.2 [7d9f7c33] + Accessors v0.1.41 [79e6a3ab] + Adapt v3.7.2 [66dad0bd] + AliasTables v1.1.3 [dce04be8] + ArgCheck v2.4.0 [ec485272] + ArnoldiMethod v0.4.0 [4fba245c] + ArrayInterface v7.5.1 [13072b0f] + AxisAlgorithms v1.1.0 [39de3d68] + AxisArrays v0.4.7 [198e06fe] + BangBang v0.4.3 [9718e550] + Baselet v0.1.1 [6e4b80f9] + BenchmarkTools v1.6.0 [d1d4a3ce] + BitFlags v0.1.9 [62783981] + BitTwiddlingConvenienceFunctions v0.1.6 [fa961155] + CEnum v0.5.0 [2a0fbf3d] + CPUSummary v0.2.6 [aafaddc9] + CatIndices v0.2.2 [d360d2e6] + ChainRulesCore v1.25.1 [9e997f8a] + ChangesOfVariables v0.1.10 [fb6a15b2] + CloseOpenIntervals v0.1.13 [aaaa29a8] + Clustering v0.15.8 [944b1d66] + CodecZlib v0.7.8 [35d6a980] + ColorSchemes v3.29.0 [3da002f7] + ColorTypes v0.12.1 [c3611d14] + ColorVectorSpace v0.11.0 [5ae59095] + Colors v0.13.1 [bbf7d656] + CommonSubexpressions v0.3.1 [34da2185] + Compat v4.16.0 [a33af91c] + CompositionsBase v0.1.2 [ed09eef8] + ComputationalResources v0.3.2 [f0e56b4a] + ConcurrentUtilities v2.5.0 [187b0558] + ConstructionBase v1.5.8 [d38c429a] + Contour v0.6.3 [150eb455] + CoordinateTransformations v0.6.3 [adafc99b] + CpuId v0.3.1 [dc8bdbbb] + CustomUnitRanges v1.0.2 [9a962f9c] + DataAPI v1.16.0 [864edb3b] + DataStructures v0.18.22 [e2d170a0] + DataValueInterfaces v1.0.0 [244e2a9f] + DefineSingletons v0.1.2 [163ba53b] + DiffResults v1.1.0 [b552c78f] + DiffRules v1.15.1 [b4f34e82] + Distances v0.10.12 [ffbed154] + DocStringExtensions v0.9.5 [460bff9d] + ExceptionUnwrapping v0.1.11 [c87230d0] + FFMPEG v0.4.2 [4f61f5a4] + FFTViews v0.3.2 [7a1cc6ca] + FFTW v1.9.0 [5789e2e9] + FileIO v1.17.0 [53c48c17] + FixedPointNumbers v0.8.5 [1fa38f19] + Format v1.3.7 [f6369f11] + ForwardDiff v1.0.1 [28b8d3ca] + GR v0.73.6 [a2bd30eb] + Graphics v1.1.3 [86223c79] + Graphs v1.12.1 [42e2da0e] + Grisu v1.0.2 [cd3eb016] + HTTP v1.10.16 [2c695a8d] + HistogramThresholding v0.3.1 [3e5b6fbb] + HostCPUFeatures v0.1.17 [47d2ed2b] + Hyperscript v0.0.5 [ac1192a8] + HypertextLiteral v0.9.5 [b5f81e59] + IOCapture v0.2.5 [615f187c] + IfElse v0.1.1 [2803e5a7] + ImageAxes v0.6.12 [c817782e] + ImageBase v0.1.7 [cbc4b850] + ImageBinarization v0.3.1 [f332f351] + ImageContrastAdjustment v0.3.12 [a09fc81d] + ImageCore v0.10.5 [89d5987c] + ImageCorners v0.1.3 [51556ac3] + ImageDistances v0.2.17 [6a3955dd] + ImageFiltering v0.7.10 [82e4d734] + ImageIO v0.6.9 [6218d12a] + ImageMagick v1.4.2 [bc367c6b] + ImageMetadata v0.9.10 [787d08f9] + ImageMorphology v0.4.6 [2996bd0c] + ImageQualityIndexes v0.3.7 [80713f31] + ImageSegmentation v1.9.0 [4e3cecfd] + ImageShow v0.3.8 [02fcd773] + ImageTransformations v0.10.2 [916415d5] + Images v0.26.2 [9b13fd28] + IndirectArrays v1.0.0 [d25df0c9] + Inflate v0.1.5 [22cec73e] + InitialValues v0.3.1 [1d092043] + IntegralArrays v0.1.6 [a98d9a8b] + Interpolations v0.15.1 [8197267c] + IntervalSets v0.7.11 [3587e190] + InverseFunctions v0.1.17 [92d709cd] + IrrationalConstants v0.2.4 [c8e1da08] + IterTools v1.4.0 [82899510] + IteratorInterfaceExtensions v1.0.0 [033835bb] + JLD2 v0.5.12 [1019f520] + JLFzf v0.1.11 [692b3bcd] + JLLWrappers v1.7.0 [682c06a0] + JSON v0.21.4 [b835a17e] + JpegTurbo v0.1.6 [b964fa9f] + LaTeXStrings v1.4.0 [23fbe1c1] + Latexify v0.16.8 [10f19ff3] + LayoutPointers v0.1.17 [8cdb02fc] + LazyModules v0.3.1 [2ab3a3ac] + LogExpFunctions v0.3.28 [e6f89c97] + LoggingExtras v1.1.0 [bdcacae8] + LoopVectorization v0.12.172 [6c6e2e6c] + MIMEs v1.1.0 [1914dd2f] + MacroTools v0.5.16 [d125e4d3] + ManualMemory v0.1.8 [dbb5928d] + MappedArrays v0.4.2 [739be429] + MbedTLS v1.1.9 [442fdcdd] + Measures v0.3.2 [626554b9] + MetaGraphs v0.8.0 [128add7d] + MicroCollections v0.2.0 [e1d29d7a] + Missings v1.2.0 [e94cdb99] + MosaicViews v0.3.4 [77ba4419] + NaNMath v1.0.3 [b8a86587] + NearestNeighbors v0.4.21 [f09324ee] + Netpbm v1.1.1 [6fe1bfb0] + OffsetArrays v1.17.0 [52e1d378] + OpenEXR v0.3.3 [4d8831e6] + OpenSSL v1.5.0 [bac558e1] + OrderedCollections v1.8.1 [f57f5aa1] + PNGFiles v0.4.4 [5432bcbf] + PaddedViews v0.5.12 [d96e819e] + Parameters v0.12.3 [69de0a69] + Parsers v2.8.3 [eebad327] + PkgVersion v0.3.3 [ccf2f8ad] + PlotThemes v3.3.0 [995b91a9] + PlotUtils v1.4.3 [91a5bcdd] + Plots v1.40.14 [7f904dfe] + PlutoUI v0.7.64 [1d0040c9] + PolyesterWeave v0.2.2 [f27b6e38] + Polynomials v4.0.19 [aea7be01] + PrecompileTools v1.2.1 [21216c6a] + Preferences v1.4.3 [92933f4c] + ProgressMeter v1.10.4 [43287f4e] + PtrArrays v1.3.0 [4b34888f] + QOI v1.0.1 [94ee1d12] + Quaternions v0.7.6 [b3c3ace0] + RangeArrays v0.3.2 [c84ed2f1] + Ratios v0.4.5 [c1ae055f] + RealDot v0.1.0 [3cdcf5f2] + RecipesBase v1.3.4 [01d81517] + RecipesPipeline v0.6.12 [189a3867] + Reexport v1.2.2 [42d2dcc6] + Referenceables v0.1.3 [dee08c22] + RegionTrees v0.3.2 [05181044] + RelocatableFolders v1.0.1 [ae029012] + Requires v1.3.1 [6038ab10] + Rotations v1.7.1 [fdea26ae] + SIMD v3.7.1 [94e857df] + SIMDTypes v0.1.0 [476501e8] + SLEEFPirates v0.6.43 [6c6a2e73] + Scratch v1.2.1 [efcf1570] + Setfield v1.1.2 [992d4aef] + Showoff v1.0.3 [777ac1f9] + SimpleBufferStream v1.2.0 [699a6c99] + SimpleTraits v0.9.4 [47aef6b3] + SimpleWeightedGraphs v1.5.0 [45858cf5] + Sixel v0.1.3 [a2af1166] + SortingAlgorithms v1.2.1 [276daf66] + SpecialFunctions v2.5.1 [171d559e] + SplittablesBase v0.1.15 [860ef19b] + StableRNGs v1.0.3 [cae243ae] + StackViews v0.1.2 [aedffcd0] + Static v0.8.9 [0d7ed370] + StaticArrayInterface v1.6.0 [90137ffa] + StaticArrays v1.9.13 [1e83bf80] + StaticArraysCore v1.4.3 [82ae8749] + StatsAPI v1.7.1 [2913bbd2] + StatsBase v0.34.4 [3783bdb8] + TableTraits v1.0.1 [bd369af6] + Tables v1.12.1 [62fd8b95] + TensorCore v0.1.1 [8290d209] + ThreadingUtilities v0.5.5 [ac1d9e8a] + ThreadsX v0.1.12 [731e570b] + TiffImages v0.11.4 [06e1c1a7] + TiledIteration v0.5.0 [3bb67fe8] + TranscodingStreams v0.11.3 [28d57a85] + Transducers v0.4.84 [410a4b4d] + Tricks v0.1.10 [5c2747f8] + URIs v1.5.2 [3a884ed6] + UnPack v1.0.2 [1cfade01] + UnicodeFun v0.4.1 [1986cc42] + Unitful v1.23.1 [45397f5d] + UnitfulLatexify v1.7.0 [41fe7b60] + Unzip v0.2.0 [3d5dd08c] + VectorizationBase v0.21.71 [e3aaa7dc] + WebP v0.1.3 [efce3f68] + WoodburyMatrices v1.0.0 [6e34b625] + Bzip2_jll v1.0.9+0 [83423d85] + Cairo_jll v1.18.5+0 [ee1fde0b] + Dbus_jll v1.16.2+0 [2702e6a9] + EpollShim_jll v0.0.20230411+1 [2e619515] + Expat_jll v2.6.5+0 [b22a6f82] + FFMPEG_jll v4.4.4+1 [f5851436] + FFTW_jll v3.3.11+0 [a3f928ae] + Fontconfig_jll v2.16.0+0 [d7e528f0] + FreeType2_jll v2.13.4+0 [559328eb] + FriBidi_jll v1.0.17+0 [0656b61e] + GLFW_jll v3.4.0+2 [d2c73de3] + GR_jll v0.73.6+0 [78b55507] + Gettext_jll v0.21.0+0 [61579ee1] + Ghostscript_jll v9.55.0+4 [59f7168a] + Giflib_jll v5.2.3+0 [7746bdde] + Glib_jll v2.84.0+0 [3b182d85] + Graphite2_jll v1.3.15+0 [2e76f6c2] + HarfBuzz_jll v8.5.1+0 [c73af94c] + ImageMagick_jll v7.1.1048+0 [905a6f67] + Imath_jll v3.1.11+0 [1d5cc7b8] + IntelOpenMP_jll v2025.0.4+0 [aacddb02] + JpegTurbo_jll v3.1.1+0 [c1c5ebd0] + LAME_jll v3.100.2+0 [88015f11] + LERC_jll v3.0.0+1 [1d63c593] + LLVMOpenMP_jll v18.1.8+0 [dd4b983a] + LZO_jll v2.10.3+0 [e9f186c6] + Libffi_jll v3.4.7+0 [7e76a0d4] + Libglvnd_jll v1.7.1+1 [94ce4f54] + Libiconv_jll v1.18.0+0 [4b2f31a3] + Libmount_jll v2.41.0+0 [89763e89] + Libtiff_jll v4.5.1+1 [38a345b3] + Libuuid_jll v2.41.0+0 [d3a379c0] + LittleCMS_jll v2.16.0+0 [856f044c] + MKL_jll v2025.0.1+1 [e7412a2a] + Ogg_jll v1.3.5+1 [18a262bb] + OpenEXR_jll v3.2.4+0 [643b3616] + OpenJpeg_jll v2.5.4+0 [458c3c95] + OpenSSL_jll v3.5.0+0 [efe28fd5] + OpenSpecFun_jll v0.5.6+0 [91d4177d] + Opus_jll v1.3.3+0 [36c8627f] + Pango_jll v1.56.3+0 [30392449] + Pixman_jll v0.44.2+0 [c0090381] + Qt6Base_jll v6.7.1+1 [a44049a8] + Vulkan_Loader_jll v1.3.243+0 [a2964d1f] + Wayland_jll v1.23.1+0 [2381bf8a] + Wayland_protocols_jll v1.44.0+0 [02c8fc9c] + XML2_jll v2.13.6+1 [ffd25f8a] + XZ_jll v5.8.1+0 [f67eecfb] + Xorg_libICE_jll v1.1.2+0 [c834827a] + Xorg_libSM_jll v1.2.6+0 [4f6342f7] + Xorg_libX11_jll v1.8.12+0 [0c0b7dd1] + Xorg_libXau_jll v1.0.13+0 [935fb764] + Xorg_libXcursor_jll v1.2.4+0 [a3789734] + Xorg_libXdmcp_jll v1.1.6+0 [1082639a] + Xorg_libXext_jll v1.3.7+0 [d091e8ba] + Xorg_libXfixes_jll v6.0.1+0 [a51aa0fd] + Xorg_libXi_jll v1.8.3+0 [d1454406] + Xorg_libXinerama_jll v1.1.6+0 [ec84b674] + Xorg_libXrandr_jll v1.5.5+0 [ea2f1a96] + Xorg_libXrender_jll v0.9.12+0 [c7cfdc94] + Xorg_libxcb_jll v1.17.1+0 [cc61e674] + Xorg_libxkbfile_jll v1.1.3+0 [e920d4aa] + Xorg_xcb_util_cursor_jll v0.1.4+0 [12413925] + Xorg_xcb_util_image_jll v0.4.1+0 [2def613f] + Xorg_xcb_util_jll v0.4.1+0 [975044d2] + Xorg_xcb_util_keysyms_jll v0.4.1+0 [0d47668e] + Xorg_xcb_util_renderutil_jll v0.3.10+0 [c22f9ab0] + Xorg_xcb_util_wm_jll v0.4.2+0 [35661453] + Xorg_xkbcomp_jll v1.4.7+0 [33bec58e] + Xorg_xkeyboard_config_jll v2.44.0+0 [c5fb5394] + Xorg_xtrans_jll v1.6.0+0 [3161d3a3] + Zstd_jll v1.5.7+1 [35ca27e7] + eudev_jll v3.2.14+0 [214eeab7] + fzf_jll v0.61.1+0 [a4ae2306] + libaom_jll v3.11.0+0 [0ac62f75] + libass_jll v0.15.2+0 [1183f4f0] + libdecor_jll v0.2.2+0 [2db6ffa8] + libevdev_jll v1.13.4+0 [f638f0a6] + libfdk_aac_jll v2.0.3+0 [36db933b] + libinput_jll v1.28.1+0 [b53b4c65] + libpng_jll v1.6.49+0 [075b6546] + libsixel_jll v1.10.5+0 [f27f6e37] + libvorbis_jll v1.3.7+2 [c5f90fcd] + libwebp_jll v1.4.0+0 [009596ad] + mtdev_jll v1.1.7+0 [1317d2d5] + oneTBB_jll v2022.0.0+0 [1270edf5] + x264_jll v2021.5.5+0 [dfaa095f] + x265_jll v3.5.0+0 [d8fb68d0] + xkbcommon_jll v1.8.1+0 [0dad84c5] + ArgTools [56f22d72] + Artifacts [2a0f44e3] + Base64 [ade2ca70] + Dates [8bb1440f] + DelimitedFiles [8ba89e20] + Distributed [f43a241f] + Downloads [7b1f6079] + FileWatching [9fa8497b] + Future [b77e0a4c] + InteractiveUtils [4af54fe1] + LazyArtifacts [b27032c2] + LibCURL [76f85450] + LibGit2 [8f399da3] + Libdl [37e2e46d] + LinearAlgebra [56ddb016] + Logging [d6f4376e] + Markdown [a63ad114] + Mmap [ca575930] + NetworkOptions [44cfe95a] + Pkg [de0858da] + Printf [9abbd945] + Profile [3fa0cd96] + REPL [9a3f8284] + Random [ea8e919c] + SHA [9e88b42a] + Serialization [1a1011a3] + SharedArrays [6462fe0b] + Sockets [2f01184e] + SparseArrays [10745b16] + Statistics [4607b0f0] + SuiteSparse [fa267f1f] + TOML [a4e569a6] + Tar [8dfed614] + Test [cf7118a7] + UUIDs [4ec0a83e] + Unicode [e66e0078] + CompilerSupportLibraries_jll [deac9b47] + LibCURL_jll [29816b5a] + LibSSH2_jll [c8ffd9c3] + MbedTLS_jll [14a3606d] + MozillaCACerts_jll [4536629a] + OpenBLAS_jll [05823500] + OpenLibm_jll [efcefdf7] + PCRE2_jll [83775a58] + Zlib_jll [8e850b90] + libblastrampoline_jll [8e850ede] + nghttp2_jll [3f19e933] + p7zip_jll
In Lecture 23 (video above), we looked at a 2D ocean model that included two physical processes: advection (flow of heat) and diffusion (spreading of heat). This homework includes the model from the lecture, and you will be able to experiment with it yourself!
The model is written in a way that it can be extended with more physical processes. In this homework we will add two more effects, introduced in the Energy Balance Model from our last homework: absorbed and emitted radiation.
Exercise 1 - Advection-diffusion
Included below is the two-dimensional advection-diffusion model from Lecture 23. To keep this homework concise, we have only included the code. To see the original notebook with more detailed comments, use the link below:
Click here to download and run the Lecture 23 notebook in a new tab.
Advection & diffusion
Notice that both functions have a main method with the following signature:
(::Array{Float64,2}, ::ClimateModel)
maps to ::Array{Float64,2}
.
As we will see later, ClimateModel
contains the grid, the velocity vector field and the simulation parameters.
advect (generic function with 3 methods)
diffuse (generic function with 3 methods)
Surround an array with one layer of zeros.
Data structures
Let's look at our first type, Grid
. Notice that it only has one 'constructor function', which takes N
(number of longitudinal grid points) and L
(longitudinal size in meters) as arguments. The struct contains more fields, these are precomputed and stored for performance.
5
300000.0
60000.0
60000.0
1×7 Matrix{Float64}: -30000.0 30000.0 90000.0 150000.0 210000.0 270000.0 330000.0
12×1 Matrix{Float64}: -330000.0 -270000.0 -210000.0 -150000.0 -90000.0 -30000.0 30000.0 90000.0 150000.0 210000.0 270000.0 330000.0
7
12
Next, let's look at three types.
Two structs: OceanModel
and OceanModelParameters
, and an abstract type: ClimateModel
.
OceanModelParameters
true
Timestepping
The OceanModel
struct contains a complete description of the model being simulated. The next struct, ClimateModelSimulation
, contains a model, together with the simulation results. It is mutable: timestepping the model means modifying a ClimateModelSimulation
object.
ClimateModelSimulation
update_ghostcells! (generic function with 1 method)
Exercise 1.1 - Running the model
In the next few cells, we set up a simulation. We have included an interactive visualisation of the simulation.
👉 Familiarize yourself with the simulation through interaction. Get a sense for each parameter by changing their values.
Uncomment (Ctrl+/
or Cmd+/
) one of the lines below to choose between the different velocity fields:
Choose the initial temperature state:
We define our ocean simulation. Run this cell again to reset the simulation to the initial state.
Simulation controls
Click to show the velocity field
Vary the current speed U: 1.0 [× reference]
Vary the diffusivity κ:
Velocity field for a single circular vortex
PointVortex (generic function with 1 method)
diagnose_velocities (generic function with 1 method)
impose_no_flux! (generic function with 1 method)
Quasi-realistic ocean velocity field
Our velocity field is given by an analytical solution to the classic wind-driven gyre problem, which is given by solving the fourth-order partial differential equation:
where the hats denote that all of the variables have been non-dimensionalized and all of their constant coefficients have been bundles into the single parameter
The solution makes use of an advanced asymptotic method (valid in the limit that
DoubleGyre (generic function with 1 method)
Some simple initial temperature fields
constantT (generic function with 1 method)
linearT (generic function with 1 method)
InitBox (generic function with 1 method)
plot_kernel (generic function with 1 method)
👉 Some parameters have a physical meaning (κ
, u
and v
), while other parameters control our numerical process. Choose two of these numerical parameters, and describe their effect on the simulation's runtime and the simulation's accuracy.
Hello!
Exercise 2 - Complexity
In this class we have restricted ourself to small problems (

Here, we provide a simple estimate of the computational complexity of climate models, which reveals a substantial challenge to the improvement of climate models.
Our climate model algorithm can be summarized by the recursive formula:
for each time step
Our goal is to simulate an ocean of fixed size (e.g.
Now, the total runtime of our simulation is proportional to the number of steps we need to take, which is
Exercise 2.1
For constant
👉 Write a function model_runtime
that takes N
as an argument, and sets up a model with grid of resolution N
, and returns the runtime of a single timestep!
.
runtime (generic function with 1 method)
Hint
To measure the runtime of a Julia command, you can do:
runtime = @elapsed do_something()
To get a more precise benchmark, you can average a fixed number of runs, by putting @elapsed
in front of a for
loop, for example.
👉 Call your runtime
function on a range of values for N
, and use a plot to demonstrate that the predicted runtime complexity holds.
8:8:200
0.611942
0.00255826
0.00558151
0.0100949
0.0157802
0.0222496
0.0288897
0.0387293
0.0492989
0.089012
0.0746905
0.0902497
0.11925
0.154679
0.142388
0.203657
0.179426
0.240757
0.234072
0.277049
0.313975
0.343459
0.368421
0.397692
0.428348
Exercise 2.2 - The CFL condition on
In Exercise 1, look for the definition of Δt
. It is currently set to 12*60*60
(12 hours).
👉 Double Δt
and run the simulation again. You should see that it runs faster, great! Now, keep doubling Δt
until you see something 'strange'. Describe what you see.
Hi!
What you experienced is a numerical instability of the discretization method in our simulation. This is not caused by floating point errors – it is a theoretical limitation of our method.
To ensure the stability of our finite-difference approximation for advection, heat should not be displaced more than one grid cell in a single timestep. Mathematically, we can ensure this by checking that the distance
or
which is known as the Courant-Freidrichs-Levy (CFL) condition.
The exact meaning of
Given below is a function CFL_advection
that takes a ClimateModel
and computes the CFL value:
CFL_advection (generic function with 1 method)
43200.0
1.42234e6
👉 Using the interactive simulation of Exercise 1, verify that the CFL condition is (somewhat) true. Increase the magnitude of
The CFL inequality states that if we want to decrease the grid spacing
Revisiting our complexity equation, we now have
In other words, in a 2-D model, 2x the spatial resolution requires 8x the computational power.
Exercise 2.3 - Moore's Law
In practice, state-of-the-art climate models are 3-D, not 2-D. It turns out that to preserve the aspect ratio of oceanic motions, the vertical grid resolution should also be increased
This is the fundamental challenge of high-performance climate computing: to increase the resolution of the models by a factor of
The figure below shows how the grid spacing of state-of-the-art climate models has decreased from

Moore's law is the observation that the number of transistors in a dense integrated circuit doubles about every two years. In the context of climate modelling, we can interpret this as meaning that the computational complexity allowed by our best high-performance computers
Present-day simulations have a grid spacing of
👉 By extrapolating Moore's law forward into the future, estimate how long it would take for
missing
Exercise 3 - Radiation
In Homework 9, we used a zero-dimensional (0-D) Energy Balance Model (EBM) to understand how Earth's average radiative imbalance results in temperature changes:
This week we will do the same, but now in two-dimensions (2-D), where in addition to heat being added or removed from the system by radiation, heat can be transported around the system by oceanic advection and diffusion (see also Lectures 22 & 23 for 1-D and 2-D advection-diffusion). The governing equation for temperature
Parameters
Below we define two new types: RadiationOceanModel
and RadiationOceanModelParameters
. Notice the similarities and differences with our original model. By making RadiationOceanModel
also a subtype of ClimateModel
, we will be able to re-use much of our original code.
RadiationOceanModelParameters
Notice that this struct has Base.@kwdef
in front of its definition. This allows us to:
assign default values to the struct fields, directly inside the definition, and
automatically create an easier constructor function that takes keyword arguments:
40000.0
1.6094376e9
210.0
-1.3
1380.0
0.3
0.55
2.0
40000.0
1.6094376e9
210.0
-1.3
2000.0
0.3
0.55
2.0
Exercise 3.1 - Absorbed radiation
The ocean absorbs solar radiation, increasing the temperature. Just like in our EBM model, we model the ocean as a surface with a temperature-dependent albedo:
α (generic function with 1 method)
An area of ocean below 0°C is covered in ice, which is more reflective, and therefore absorbs less solar radiation. In our EBM model, this positive feedback leads to a bifurcation: under the same external conditions, the climate system has multiple equilibria.
In this week's two-dimensional model, the factor
Here is a second method for α
that takes a 2D array T
with the current ocean temperatures and a RadiationOceanModel
, and returns the 2D array of albedos. We use the dot operator to apply α
pointwise to T
, also called broadcasting.
α (generic function with 2 methods)
Solar insolation
Our rectangular grid represents the North Atlantic Ocean, stretching from the equator (latitude = 0°) to the North Pole (latitude = 90°) in the latitudinal direction (y
), and from the east coast of North America to the west coast of Europe in the longitudinal direction (x
). In reality, climate models have to explicitly deal with the curvature of the Earth when constructing their model grids. Here, we will just treat the North Atlantic Ocean as a rectangle with roughly the correct dimensions.
Just like the albedo, every grid cell will have a local amount of solar insolation. In our model, we use the annual average at the latitude of a grid cell
S_at (generic function with 1 method)
Note that latitude is the horizontal axis in this graph, not the vertical.
y_to_lat (generic function with 1 method)
👉 Write a method absorbed_solar_radiation
that takes a 2D array T
with the current ocean temperatures and a RadiationOceanModel
, and returns the tendencies corresponding to absorbed radiation. This is the analogue of advect
and diffuse
.
absorbed_solar_radiation (generic function with 1 method)
Exercise 3.2 - Outgoing radiation
Just like in our EBM from before, when our ocean heats up by absorbing solar radiation, it also emits radiation back to space. This outgoing thermal radiation is what allows the ocean to eventually come to an equilibrium. The difference here is that each individual grid cell of our model radiatives according to it's local temperature
outgoing_thermal_radiation (generic function with 1 method)
👉 Write a method outgoing_termal_radiation
that takes a 2D array T
with the current ocean temperatures and a RadiationOceanModel
, and returns the tendencies corresponding to outgoing radiation. This is the analogue of advect
and diffuse
.
outgoing_thermal_radiation (generic function with 2 methods)
Exercise 3.3 - Running the model
Let's define a new timestep!
method for our new model. This is exactly the same as our advection-diffusion model, with the addition of the two radiation tendencies.
timestep! (generic function with 2 methods)
We can now simulate our radiation ocean model, reusing much of the code from our advection-diffusion simulation.
10
6.0e6
600000.0
600000.0
1×12 Matrix{Float64}: -300000.0 300000.0 900000.0 1.5e6 2.1e6 … 3.9e6 4.5e6 5.1e6 5.7e6 6.3e6
22×1 Matrix{Float64}: -6.3e6 -5.7e6 -5.1e6 -4.5e6 -3.9e6 -3.3e6 -2.7e6 ⋮ 3.3e6 3.9e6 4.5e6 5.1e6 5.7e6 6.3e6
12
22
40000.0
1.6094376e9
210.0
-1.3
1380.0
0.3
0.55
2.0
22×12 Matrix{Float64}: 0.0 0.0 0.0 0.0 … 0.0 0.0 0.0 0.0 -0.00429516 -0.00742693 -0.00597958 -0.00121706 -0.000523235 0.0 0.0 -0.00387472 -0.00669993 -0.00539425 -0.00109793 -0.000472017 0.0 0.0 -0.00307499 -0.0053171 -0.0042809 -0.000871319 -0.000374595 0.0 0.0 -0.00197427 -0.00341379 -0.00274851 -0.000559421 -0.000240505 0.0 0.0 -0.000680286 -0.00117631 -0.000947072 … -0.000192763 -8.28722e-5 0.0 0.0 0.000680286 0.00117631 0.000947072 0.000192763 8.28722e-5 0.0 ⋮ ⋱ ⋮ 0.0 -0.000680286 -0.00117631 -0.000947072 -0.000192763 -8.28722e-5 0.0 0.0 -0.00197427 -0.00341379 -0.00274851 -0.000559421 -0.000240505 0.0 0.0 -0.00307499 -0.0053171 -0.0042809 -0.000871319 -0.000374595 0.0 0.0 -0.00387472 -0.00669993 -0.00539425 -0.00109793 -0.000472017 0.0 0.0 -0.00429516 -0.00742693 -0.00597958 … -0.00121706 -0.000523235 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
22×12 Matrix{Float64}: 0.0 0.0 0.0 0.0 … 0.0 0.0 0.0 0.0 0.00429516 -0.00116338 -0.000283974 -0.000401154 -0.000292671 0.0 0.0 0.012465 -0.00337627 -0.000824126 -0.00116419 -0.000849366 0.0 0.0 0.0194148 -0.00525867 -0.00128361 -0.00181328 -0.00132292 0.0 0.0 0.024464 -0.00662631 -0.00161744 -0.00228486 -0.00166697 0.0 0.0 0.0271186 -0.00734532 -0.00179294 … -0.00253279 -0.00184785 0.0 0.0 0.0271186 -0.00734532 -0.00179294 -0.00253279 -0.00184785 0.0 ⋮ ⋱ ⋮ 0.0 -0.0271186 0.00734532 0.00179294 0.00253279 0.00184785 0.0 0.0 -0.024464 0.00662631 0.00161744 0.00228486 0.00166697 0.0 0.0 -0.0194148 0.00525867 0.00128361 0.00181328 0.00132292 0.0 0.0 -0.012465 0.00337627 0.000824126 0.00116419 0.000849366 0.0 0.0 -0.00429516 0.00116338 0.000283974 … 0.000401154 0.000292671 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
22×12 Matrix{Float64}: 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 ⋮ ⋮ ⋮ 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0 10.0
1.44e6
0
👉 Play around with the simulation to find the effect of each parameter. In particular, discover the effect of the solar insolation, S_mean
, the initial temperatures, T_init
, the liquid and ice albedos: α0
and αi
, and the amount of emitted heat at 0°C, A
.
Exercise 3.4 - Stable states
So far, we are able to set up a model and run it interactively. You see that the model quickly goes from the initial temperatures to a stable state: a state with balanced energy (radiation out, radiation in). Changing the initial state slightly will probably result in the same stable state.
But let's see what happens when we initialize with extremely high or low initial temperatures...
👉 For T_init_value=-50
give a different result than T_init_value=+50
? What about T_init_value=+55
? By trying various values for T_init_value
, how many stable states do you find?
I found ...
👉 Answer the same question for
I found ...
I found ...
Exercise 3.5
That's right, we have found a bifurcation! Under the right conditions, there are multiple stable states. But under different conditions, there is only one stable state.
Hypothesis: The multiple stable states at
👉 Find a way to confirm this hypothesis by changing the model parameters in the interactive model. Describe your findings.
Bonjour !
👉 Why is the number of stable states different for a lower or higher value of
Hi! 🍪
Exercise 4 - Bifurcation diagram
So far, we are able to set up a model and run it interactively, and we discovered that by changing the initial value of S_mean
, we find a different number of stable states.
In this final exercise, we will generate a visualization to help us understand the relationship between S_mean
and the number of stable states. Instead of running a single model interactively, we write a function that takes the model parameters as input, runs the model until equilibrium, and returns the final mean temperature. We will run this high-level function for various initial values, generating a single graph: the bifurcation diagram.
Exercise 4.1 - Equilibrium temperature
👉 Write a function eq_T
that takes two argments, S
and T_init_value
, that sets up a radiation ocean model with S
as S_mean
, and with T_init_value
as the constant initial temperature. Run the model until you have reached equilibrium (approximately), and return the average temperature.
eq_T (generic function with 1 method)
Hint
How do you determine that the model has reached equilibrium?
The simplest way is to use the interactive simulation above to find a fixed time/number of steps, for which any initial value has reached equilibrium.
Using a long time period is more accurate, but it means that the runtime will be long. If this is a problem, you can use a dynamic stopping condition instead. For example, you can stop the simulation early when the total incoming and total outgoing radiation are roughly equal.
👉 Use the function eq_T
to verify your answer to Exercise 3.4.
Hint
Create an array of values for T_init_value
(not too many!), and run eq_T
for each. Find clusters in the results.
This is a good opportunity to check whether your implementation of eq_T
is correct! Use the interactive simulation to check the results manually.
Exercise 4.2
👉 Make a bifurcation diagram. For a couple of pairs (S,T_init)
, calculate the equilibrium temperature. Create a scatter plot with
This calculation can take quite some time. Some tips:
Start out with a small amount of points.
Run the
eq_T
calculations in one cell, and store the result as a vector. Generate the scatter plot in a different cell.You can replace a
map
withThreadsX.map
to run it in parallel across multiple CPU cores. More on this below.
1000
-50
1000
0
1000
50
1380
-50
1380
0
1380
50
2000
-50
2000
0
2000
50
-60.5801
-61.7385
-61.9387
-32.5379
5.42921
28.728
103.569
101.608
102.066
Parallelize a map
You use map
to apply a function to each element of a vector. Why not use a for
loop? One nice property of map
code is that you only describe the operation for each element, not the order to run the operations in. This means that it can be easily parallelized by the computer. For example, on a computer with 4 cores, the computation map(sqrt, 1:100)
can be parallelized by handling 1:25
on the first core, 26:50
on the second, etc., at the same time.
In Julia, many functional primitives (map
, filter
, sum
, maximum
, all
, and more) have an automatically multithreaded version, in the ThreadsX.jl
package. As a demo, compare the two cells below. (You can see the runtime in the bottom right of a cell.) You might need to run the cells a second time, the first time includes Julia's compiler doing its thing.
1
4
9
16
25
36
49
64
1
4
9
16
25
36
49
64
Exercise XX: Lecture transcript
(MIT students only)
Please see the link for the transcript document on Canvas. We want each of you to correct about 500 lines, but don’t spend more than 20 minutes on it. See the the beginning of the document for more instructions.
👉 Please mention the name of the video(s) and the line ranges you edited:
Abstraction, lines 1-219; Array Basics, lines 1-137; Course Intro, lines 1-144 (for example)
Before you submit
Remember to fill in your name and Kerberos ID at the top of this notebook.
Appendix
plot_state (generic function with 1 method)
Function library
Just some helper functions used in the notebook.
hint (generic function with 1 method)
almost (generic function with 1 method)
still_missing (generic function with 2 methods)
keep_working (generic function with 2 methods)
Fantastic!
Splendid!
Great!
Yay ❤
Great! 🎉
Well done!
Keep it up!
Good job!
Awesome!
You got the right answer!
Let's move on to the next section.
correct (generic function with 2 methods)
not_defined (generic function with 1 method)
todo (generic function with 1 method)